﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SpeakupBackend.Themes;
using SpeakupBackend.Classes;
using TableParsers;

namespace SpeakupTests.SpeakupBackend.Themes.Group
{
    [TestClass]
    public class GroupThemeTests
    {
        [TestMethod]
        public void Create()
        {
            List<String> names = new List<string> { "name1", "name2", "name3" };

            foreach (Level lvl in Level.GetLevels())
            {
                foreach (GroupThemeName gtName in Enum.GetValues(typeof(GroupThemeName)))
                {
                    GroupTheme th = new GroupTheme(gtName, lvl);
                    Assert.AreEqual(lvl, th.Level);
                    Assert.AreEqual(gtName, th.GroupThemeName);
                    Assert.AreEqual(gtName.ToString(), th.Name);

                    th = new GroupTheme(gtName.ToString(), lvl);
                    Assert.AreEqual(lvl, th.Level);
                    Assert.AreEqual(gtName, th.GroupThemeName);
                    Assert.AreEqual(gtName.ToString(), th.Name);
                }
            }            
        }

        [TestMethod]
        public void ObjectEquals()
        {
            GroupThemeName name = GroupThemeName.Blue;

            foreach (Level leftLevel in Level.GetLevels())
            {
                foreach (Level rightLevel in Level.GetLevels())
                {
                    Object leftTh = new GroupTheme(name, leftLevel);
                    Object rightTh = new GroupTheme(name, rightLevel);

                    Assert.AreEqual(leftTh.Equals(rightTh), leftLevel == rightLevel);
                    Assert.AreEqual(rightTh.Equals(leftTh), leftLevel == rightLevel);
                }                
            }

            Level level = Level.GetLevel(1);
            foreach (GroupThemeName nLeft in Enum.GetValues(typeof(GroupThemeName)))
            {
                foreach (GroupThemeName nRight in Enum.GetValues(typeof(GroupThemeName)))
                {
                    Object leftTh = new GroupTheme(nLeft, level);
                    Object rightTh = new GroupTheme(nRight, level);

                    Assert.AreEqual(rightTh.Equals(leftTh), nLeft == nRight);
                    Assert.AreEqual(leftTh.Equals(rightTh), nLeft == nRight);
                }
            }      
        }

        [TestMethod]
        public void Equals()
        {
            GroupThemeName name = GroupThemeName.Blue;

            foreach (Level leftLevel in Level.GetLevels())
            {
                foreach (Level rightLevel in Level.GetLevels())
                {
                    GroupTheme leftTh = new GroupTheme(name, leftLevel);
                    GroupTheme rightTh = new GroupTheme(name, rightLevel);

                    Assert.AreEqual(leftTh.Equals(rightTh), leftLevel == rightLevel);
                    Assert.AreEqual(rightTh.Equals(leftTh), leftLevel == rightLevel);
                }
            }

            Level level = Level.GetLevel(1);
            foreach (GroupThemeName nLeft in Enum.GetValues(typeof(GroupThemeName)))
            {
                foreach (GroupThemeName nRight in Enum.GetValues(typeof(GroupThemeName)))
                {
                    GroupTheme leftTh = new GroupTheme(nLeft, level);
                    GroupTheme rightTh = new GroupTheme(nRight, level);

                    Assert.AreEqual(rightTh.Equals(leftTh), nLeft == nRight);
                    Assert.AreEqual(leftTh.Equals(rightTh), nLeft == nRight);
                }
            }
        }

        [TestMethod]
        public new void GetHashCode()
        {
            GroupThemeName name = GroupThemeName.Blue;

            foreach (Level leftLevel in Level.GetLevels())
            {
                foreach (Level rightLevel in Level.GetLevels())
                {
                    GroupTheme leftTh = new GroupTheme(name, leftLevel);
                    GroupTheme rightTh = new GroupTheme(name, rightLevel);

                    Assert.AreEqual(leftTh.GetHashCode() ==  rightTh.GetHashCode(), leftLevel == rightLevel);
                    
                }
            }

            Level level = Level.GetLevel(1);
            foreach (GroupThemeName nLeft in Enum.GetValues(typeof(GroupThemeName)))
            {
                foreach (GroupThemeName nRight in Enum.GetValues(typeof(GroupThemeName)))
                {
                    GroupTheme leftTh = new GroupTheme(nLeft, level);
                    GroupTheme rightTh = new GroupTheme(nRight, level);

                    Assert.AreEqual(leftTh.GetHashCode() == rightTh.GetHashCode(), nLeft == nRight);
                }
            }
        }

        [TestMethod]
        public void CompareTo()
        {
            GroupThemeName name = GroupThemeName.Blue;

            foreach (Level leftLevel in Level.GetLevels())
            {
                foreach (Level rightLevel in Level.GetLevels())
                {
                    GroupTheme leftTh = new GroupTheme(name, leftLevel);
                    GroupTheme rightTh = new GroupTheme(name, rightLevel);

                    Assert.AreEqual(
                        Math.Sign(leftTh.CompareTo(rightTh)), 
                        Math.Sign(leftLevel.CompareTo(rightLevel)) );

                    Assert.AreEqual(
                        Math.Sign(rightTh.CompareTo(leftTh)),
                        Math.Sign(rightLevel.CompareTo(leftLevel)));
                    
                }
            }

            Level level = Level.GetLevel(1);
            foreach (GroupThemeName nLeft in Enum.GetValues(typeof(GroupThemeName)))
            {
                foreach (GroupThemeName nRight in Enum.GetValues(typeof(GroupThemeName)))
                {
                    GroupTheme leftTh = new GroupTheme(nLeft, level);
                    GroupTheme rightTh = new GroupTheme(nRight, level);

                    Assert.AreEqual(
                        Math.Sign(leftTh.CompareTo(rightTh)),
                        Math.Sign(nLeft.CompareTo(nRight)));

                    Assert.AreEqual(
                        Math.Sign(rightTh.CompareTo(leftTh)),
                        Math.Sign(nRight.CompareTo(nLeft)));
                }
            }
        }

        
        [TestMethod]
        public void CompareOperators()
        {
            GroupThemeName name = GroupThemeName.Blue;

            foreach (Level leftLevel in Level.GetLevels())
            {
                foreach (Level rightLevel in Level.GetLevels())
                {
                    GroupTheme leftTh = new GroupTheme(name, leftLevel);
                    GroupTheme rightTh = new GroupTheme(name, rightLevel);

                    Assert.AreEqual(leftTh == rightTh, leftLevel == rightLevel);
                    Assert.AreEqual(leftTh != rightTh, leftLevel != rightLevel);
                    Assert.AreEqual(leftTh < rightTh, leftLevel < rightLevel);
                    Assert.AreEqual(leftTh <= rightTh, leftLevel <= rightLevel);
                    Assert.AreEqual(leftTh > rightTh, leftLevel > rightLevel);
                    Assert.AreEqual(leftTh >= rightTh, leftLevel >= rightLevel);
                }
            }

            Level level = Level.GetLevel(1);
            foreach (GroupThemeName nLeft in Enum.GetValues(typeof(GroupThemeName)))
            {
                foreach (GroupThemeName nRight in Enum.GetValues(typeof(GroupThemeName)))
                {
                    GroupTheme leftTh = new GroupTheme(nLeft, level);
                    GroupTheme rightTh = new GroupTheme(nRight, level);

                    Assert.AreEqual(leftTh == rightTh, nLeft == nRight);
                    Assert.AreEqual(leftTh != rightTh, nLeft != nRight);
                    Assert.AreEqual(leftTh < rightTh, nLeft < nRight);
                    Assert.AreEqual(leftTh <= rightTh, nLeft <= nRight);
                    Assert.AreEqual(leftTh > rightTh, nLeft > nRight);
                    Assert.AreEqual(leftTh >= rightTh, nLeft >= nRight);
                }
            }
        }


        Class CreateClass(Level level, ClassType classType, String name)
        {
            int unit = 0;
            if (level != null)
            {
                unit = level.GetUnits().First();
            }

            return new Class(0, new ClassName(name.ToString(), name, classType),
                                new ClassTime(DateTime.Now, TimeSpan.FromHours(12), TimeSpan.FromHours(13)),
                                unit, ClassStatus.Cancelled, ClassAction.None);
        }

        [TestMethod]
        public void IsCompatibleClass()
        {
            GroupTheme theme = new GroupTheme(GroupThemeName.Blue, Level.GetLevel(1));

            Class nullUnitClass = CreateClass(null, GroupTheme.ValidClassType, theme.GroupThemeName.ToString());
            Assert.IsFalse(theme.IsCompatibleClass(nullUnitClass));


            Class badNameClass = CreateClass(Level.GetLevel(1), 
                                             GroupTheme.ValidClassType,
                                             theme.Name + "--postfix");
            Assert.IsFalse(theme.IsCompatibleClass(badNameClass));

            foreach (Level thLevel in Level.GetLevels())
            {
                foreach (GroupThemeName thName in Enum.GetValues(typeof(GroupThemeName)))
                {
                    theme = new GroupTheme(thName, thLevel);

                    foreach (Level clLevel in Level.GetLevels())
                    {
                        foreach (GroupThemeName clName in Enum.GetValues(typeof(GroupThemeName)))
                        {
                            Class cl = CreateClass(clLevel, GroupTheme.ValidClassType, clName.ToString());

                            Assert.AreEqual(theme.IsCompatibleClass(cl),
                                            thLevel == clLevel && thName == clName);

                        }
                    }

                }
            }


        }
    }
}
